home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / timidsrc.zip / bag.c next >
C/C++ Source or Header  |  1996-05-20  |  4KB  |  178 lines

  1. /*
  2.  
  3.     bag -- A quick hack to buffer audio data between TiMidity and an
  4.            external player program.
  5.  
  6.     This program is in the Public Domain. It is distributed without
  7.     much hope that it will be useful, and WITHOUT ANY WARRANTY;
  8.     definitely without any implied warranty of MERCHANTABILITY or
  9.     FITNESS FOR ANY PURPOSE.
  10.  
  11.     bag may enable you to play complex files at higher output rates,
  12.     but it's a bit of a pain to use.
  13.  
  14.     Here's a usage example for Linux. splay is a program that (with
  15.     this invocation) plays audio data from stdin. Your flag
  16.     requirements may vary.
  17.  
  18.         timidity -id -Or1lsS -o- -s22 -p48 filenames |
  19.         bag -b 2M -t 1M -c 4k |
  20.         splay -b16 -s22 -S
  21.  
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <limits.h>
  28. #include <sys/time.h>
  29. #include <sys/types.h>
  30. #include <unistd.h>
  31. #include <errno.h>
  32.  
  33. static int bytes(char *s)
  34. {
  35.   int i;
  36.   i=atoi(s);
  37.   while (*s>='0' && *s<='9')
  38.     s++;
  39.  
  40.   switch(*s)
  41.     {
  42.     case 'm':
  43.     case 'M':
  44.       i *= 1024;
  45.     case 'k':
  46.     case 'K':
  47.       i *= 1024;
  48.     }
  49.   return i;
  50. }
  51.  
  52. int main(int argc, char **argv)
  53. {
  54.   int bs=1024*1024, rs=4*1024, ws=4*1024, cs=4*1024, thresh=64*1024;
  55.   int c, junk=0, verbosity=0, flush_and_go=0;
  56.   char *bag, *head, *tail;
  57.   extern char *optarg; /* for Sun's gcc */
  58.  
  59.   fd_set readfds, writefds, brokefds;
  60.   struct timeval tmo;
  61.  
  62.   while ((c=getopt(argc, argv, "b:t:r:w:c:hv"))>0)
  63.     switch(c)
  64.       {
  65.       case 'b': bs=bytes(optarg); break;
  66.       case 't': thresh=bytes(optarg); break;
  67.       case 'r': rs=bytes(optarg); break;
  68.       case 'w': ws=bytes(optarg); break;
  69.       case 'c': rs=ws=bytes(optarg); break;
  70.       case 'v': verbosity++; break;
  71.       case '?':
  72.       case 'h':
  73.     printf("\nBag usage:\n\n"
  74.            "  timidity -id -Or[format options] -o- [options and filenames] |\n"
  75.            "  bag [bag options] | audio_player [player options]\n\n"
  76.            "Bag options:\n\n"
  77.            "  -b size    Set buffer size (default %d)\n"
  78.            "  -r size    Set read chunk size (default %d)\n"
  79.            "  -w size    Set write chunk size (default %d)\n"
  80.            "  -c size    Set read/write chunk size\n"
  81.            "  -t size    Set start threshold for writing (default %d)\n"
  82.            "  -v         Verbose mode\n"
  83.            "  -h         This help screen\n\n"
  84.            ,bs,rs,ws,thresh);
  85.     return 0;
  86.       }
  87.  
  88.   if (ws>rs) cs=ws;
  89.   else cs=rs;
  90.   if (bs < ws+rs)
  91.     {
  92.       bs=ws+rs;
  93.       fprintf(stderr, "bag: Buffer size increased to %d bytes\n", bs);
  94.     }
  95.   if (thresh > (bs-rs))
  96.     {
  97.       thresh=bs-rs;
  98.       fprintf(stderr, "bag: Threshold lowered to %d bytes\n", bs);
  99.     }
  100.  
  101.   head=tail=bag=malloc(bs);
  102.   junk=0;
  103.   while (!flush_and_go)
  104.     {
  105.       FD_ZERO(&readfds);
  106.       FD_ZERO(&writefds);
  107.       FD_ZERO(&brokefds);
  108.  
  109.       if (junk<(bs-rs))
  110.     FD_SET(STDIN_FILENO, &readfds);
  111.  
  112.       if (junk>ws && junk>thresh)
  113.     {
  114.       FD_SET(STDOUT_FILENO, &writefds);
  115.       thresh=0;
  116.     }
  117.       
  118.       FD_SET(STDIN_FILENO, &brokefds);
  119.       FD_SET(STDOUT_FILENO, &brokefds);
  120.       
  121.       tmo.tv_sec=1;
  122.       tmo.tv_usec=0;
  123. #ifdef HPUX
  124.       if ((c=select(FD_SETSIZE,(int *) &readfds,(int *) &writefds, (int *) &brokefds, &tmo))<0)
  125. #else
  126.       if ((c=select(FD_SETSIZE, &readfds, &writefds, &brokefds, &tmo))<0)
  127. #endif
  128.     perror("\nbag: select");
  129.  
  130.       if (verbosity)
  131.     fprintf(stderr, "\rbag: %8d bytes", junk);
  132.  
  133.       if (FD_ISSET(STDOUT_FILENO, &brokefds))
  134.     {
  135.       fprintf(stderr, "\nbag: Elvis has left the building\n");
  136.       return 1;
  137.     }
  138.  
  139.       if (FD_ISSET(STDIN_FILENO, &readfds))
  140.     {
  141.       if ((c=read(STDIN_FILENO, head, 
  142.               (head+rs >= bag+bs) ? (bag+bs-head) : rs))<=0)
  143.         {
  144.           if (c==0 || errno!=EAGAIN)
  145.         flush_and_go=1;
  146.         }
  147.       else
  148.         {
  149.           junk+=c;
  150.           head+=c;
  151.           if (head>=bag+bs)
  152.         head-=bs;
  153.         }
  154.     }
  155.       else if (FD_ISSET(STDIN_FILENO, &brokefds))
  156.     flush_and_go=1;
  157.  
  158.       if (flush_and_go || FD_ISSET(STDOUT_FILENO, &writefds))
  159.     do
  160.       {
  161.         c=(tail+ws >= bag+bs) ? (bag+bs-tail) : ws;
  162.         if (c>junk) c=junk;
  163.         
  164.         if (flush_and_go && verbosity)
  165.           fprintf(stderr, "\rbag: Flushing, %8d bytes", junk);
  166.         
  167.         c=write(STDOUT_FILENO, tail, c);
  168.         junk -= c;
  169.         tail += c;
  170.         if (tail>=bag+bs)
  171.           tail-=bs;
  172.       } while (flush_and_go && junk);
  173.     }
  174.   if (verbosity)
  175.     fprintf(stderr, "\nbag: All done\n");
  176.   return 0;
  177. }
  178.